package multi;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import GUI.lafenetre;



public class multithread {
	
    public int progress;
    private lafenetre something;
    
    //////////////CONSTRUCTOR//////////////
    public multithread(lafenetre something){
    	this.something = something;
    }
    
	 public static double mamultifonction(final int nSteps, final double drift, final double vSqrdt, final double st, final int nSimulations,final double X,final double T, final int z) 
		      throws InterruptedException, ExecutionException {      
		    final int numberOfCores = Runtime.getRuntime().availableProcessors();
		    final double blockingCoefficient = 0.1;
		    final int poolSize = (int)(numberOfCores / (1 - blockingCoefficient));
		    
		    //System.out.println("Number of Cores available is " + numberOfCores);
		    System.out.println("Pool size is " + poolSize);
		    final List<Callable<Double>> partitions = 
		      new ArrayList<Callable<Double>>();
		    for(int i=1; i<=nSimulations; i++) {
		      partitions.add(new Callable<Double>() {
		        public Double call() throws Exception {
		            double st2= st;
		            Random rand = new Random();
		            for (int j=1; j<=nSteps; j++){
		                st2 *= Math.exp(drift + vSqrdt * rand.nextGaussian());
		            }
		          return st2;
		        }        
		      });
		    }
		        
		    final ExecutorService executorPool = 
    	      Executors.newFixedThreadPool(poolSize);    
    	    final List<Future<Double>> valueOfStocks = 
    	      executorPool.invokeAll(partitions, 10000, TimeUnit.SECONDS);
    	      double sum =0;
    	    for(final Future<Double> valueOfAStock : valueOfStocks)  
    	    sum = sum + Math.max(z*(valueOfAStock.get()-X), 0);

    	    executorPool.shutdown();
    	    return sum;   
		  } 
	 
		public static double MonteCarloStandardOption(String CallPutFlag, double S, 
				double X, double T, double r, double b, double v, int nSteps, int nSimulations) throws InterruptedException, ExecutionException
		{
			
		      //Variables
				  int z;
				  double dt = T / nSteps;
				  double Drift = (b - v*v / 2) * dt;
				  double vSqrdt = v * java.lang.Math.sqrt(dt);
				  double Sum = 0;
				  
				  double MonteCarloStandardOption;
			      
			      //Check if this is a call or a put (c or p)
				  if ("c".equals(CallPutFlag)) z=1;
			      else if ("p".equals(CallPutFlag))z=-1;
			      else z=0;
	    
		        Sum = mamultifonction(nSteps, Drift, vSqrdt, S,nSimulations,X, T, z);
	        
			      MonteCarloStandardOption = Math.exp( -r * T) * (Sum / nSimulations);
			      return MonteCarloStandardOption;

		}

		}
